package com.blockmeta.bbs.businesslibrary.widget.chartview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import androidx.core.view.ViewCompat;
import androidx.core.widget.ScrollerCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;

import com.blockmeta.bbs.baselibrary.base.app.BaseApp;
import com.blockmeta.bbs.businesslibrary.R;
import com.blockmeta.bbs.businesslibrary.business.DataManager;
import com.blockmeta.bbs.businesslibrary.websocket.AppDefine;
import com.blockmeta.bbs.businesslibrary.widget.chartview.Layer.Layer;
import com.blockmeta.bbs.businesslibrary.widget.tictactec.ta.lib.Core;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 适用于和symbol相关的图表，不适用于其他图表
 */
public class CoinChart extends View {


    //获得chart类型
    public enum ChartModeEnum {
        Symbol(0);

        int m_nId;

        ChartModeEnum(int pID) {
            m_nId = pID;
        }

        public static ChartModeEnum FromID(int pID) {
            for (ChartModeEnum tType : values()) {
                if (tType.m_nId == pID) {
                    return tType;
                }
            }
            return Symbol;
        }
    }

    public enum PointLocation {
        TOPRIGHT, TOPLEFT, BOTTOMRIGHT, BOTTOMLEFT;
    }

    /**
     * 如果设置为bottomleft后需要在右侧显示百分比
     */
    public enum AxisPercentType {
        NOPERCENT, BOTTOMPERCENT, MIDDLEPERCENT;
    }

    private static int ChartSubKeyIndex = 0;
    public static final String PERIODQUERY = "PERIODQUERY";

    private static synchronized int getChartSubKeyIndex() {
        return ++ChartSubKeyIndex;
    }

    private String m_chartSubKey;

    private List<Layer> m_arrLayerList = null;
    private Paint m_paint = null;
    private int m_nMeasureWidth = -1;
    private int m_nMeasureHeight = -1;
    private String m_strSymbolCode = "";
    private ChartData.ChartPeroid m_enChartType = ChartData.ChartPeroid.CP_1min;
    private ChartModeEnum m_enChartMode = ChartModeEnum.Symbol;
    private int m_nSysUpColor = 0;
    private int m_nSysDownColor = 0;
    private int m_nSysBgColor = 0;
    private int m_nSysEvenColor = 0;
    private int m_nXTagCount = 0;
    private Point m_point;
    private Point m_pointRow;

    private boolean m_bIsDrag = false;
    private Point m_pointStart;
    private int mTouchSlop;
    private FDTChartCallback m_callback = null;//图的一些回调点击事件
    private IDataCallback m_callbackData = null;//获取数据的一些回调事件
    public ChartData m_chartData;

    private Timer m_timer = new Timer(true);
    private boolean m_bLongPress = false;
    private boolean m_bLongLongPress = false;
    private boolean m_needLongLongPress = false;

    private final int LONGPRESS = 1234;
    private final int LONGLONGPRESS = 2345;
    private long m_lPressTime = 600;
    private long m_llPressTime = 800;
    private long m_llPressTime2 = 800;
    public static final int LongPressDelay = 3000;


    public static int getBorderColor() {
//        return Color.parseColor("#d9d9d9");
        return "night".equals(getSkincode()) ? Color.parseColor("#1E202C") : Color.parseColor("#EDEDED");
    }

    public static int getCrossRectColor() {
//        return Color.parseColor("#d9d9d9");
        return "night".equals(getSkincode()) ? Color.parseColor("#2E3547") : Color.parseColor("#D3D7E0");
    }

    public static int getCrossTextColor() {
//        return Color.parseColor("#d9d9d9");
        return "night".equals(getSkincode()) ? Color.parseColor("#FFFFFF") : Color.parseColor("#333333");
    }

    public static int m_nBorderColor = getBorderColor();//get0xFFCDE5FF;
    private float m_fBorderWidth = 3.f;

    public static String getSkincode() {
        return m_skincode;
    }

    public static String m_skincode = "light";

    /**
     * 缩放相关
     */
    public boolean mCanMove;//能否平移缩放
    public boolean mCanScale;//在canmove true基础上才能控制能否缩放
    public boolean mZoomMode;//只有放大缩小模式
    public boolean mShouldIntercept;//能否平移缩放
    private int mZoomFocusX;
    private ScaleGestureDetector mScaleDetector;
    private VelocityTracker mVelocityTracker;
    private float mScaleFactor;//放大因子
    public static final float DEFAULT_SCALEFACTOR = 1.0f;
    private float mStepX;//步长
    private float mTouchStartX;
    private static final int MAX_CLICK_DURATION = 200;
    private long mStartClickTime;
    private int mMinimumFlingVelocity;
    private int mMaximumFlingVelocity;
    private ScrollerCompat mScroller;//滑动器
    private float mChartContentLeft;//记录图表内容区域的左边x坐标,用于判断缩放的区域在屏幕的百分比位置
    private float mChartContentWidth;//记录图表内容区域的宽度
    private boolean mIsLandScape;
    private boolean mIsShowProgressBar;
    private Date mllRecordTime = new Date();
    public static boolean is8btcStyle = true;

    private RectF mChartRect;


    //由于core较大,维持一份
    private static class SingletonHolder {
        private static final Core taLib = new Core();
    }

    public static final Core getTaLib() {
        return SingletonHolder.taLib;
    }


    public boolean canMove() {
        return mCanMove && m_chartData != null && m_chartData.getCount() != 0;
    }

    public void setCanMove(boolean pCanMove) {
        this.mCanMove = pCanMove;
    }

    public boolean canScale() {
        return mCanScale;
    }

    public void setCanScale(boolean mCanScale) {
        this.mCanScale = mCanScale;
    }

    public void setShouldIntercept(boolean mShouldIntercept) {
        this.mShouldIntercept = mShouldIntercept;
    }

    /**
     * 是否需要出现交易面板
     *
     * @param m_needLongLongPress
     */
    public void setNeedLongLongPress(boolean m_needLongLongPress) {
        this.m_needLongLongPress = m_needLongLongPress;
    }

    public boolean isLandScape() {
        return mIsLandScape;
    }

    public void setIsLandScape(boolean mIsLandScape) {
        this.mIsLandScape = mIsLandScape;
    }

    public void setIsDrawRect(boolean m_IsDrawRect) {
        this.m_IsDrawRect = m_IsDrawRect;
    }

    private boolean m_IsDrawRect = true;

    private OnClickListener m_listenerClick = null;

    private boolean m_bIsSimpleMode = false;

    private Bitmap m_bitmapArrowLeft, m_bitmapArrowRight;

    private boolean m_bIsCoordinateTextOuterY = true;

    public CoinChart(Context context) {
        super(context);
        initialize(context, Layer.ChartTypeEnum.KBAR, ChartModeEnum.Symbol, false, 3);
    }

    public CoinChart(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CoinChart(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray tTypeeArr = context.obtainStyledAttributes(attrs, R.styleable.BLOCKMETAChart, defStyleAttr, 0);

        int tValue = tTypeeArr.getInt(R.styleable.BLOCKMETAChart_ChartType, 0);
        Layer.ChartTypeEnum tType = Layer.ChartTypeEnum.fromID(tValue);
        tValue = tTypeeArr.getInt(R.styleable.BLOCKMETAChart_ChartMode, 0);
        ChartModeEnum tMode = ChartModeEnum.FromID(tValue);
        boolean tGradient = tTypeeArr.getBoolean(R.styleable.BLOCKMETAChart_gradient, false);
        tValue = tTypeeArr.getInt(R.styleable.BLOCKMETAChart_XTagCount, 3);
        tTypeeArr.recycle();
        initialize(context, tType, tMode, tGradient, tValue);

    }

    //
    private void initialize(Context pContext, Layer.ChartTypeEnum pType, ChartModeEnum pMode, boolean pGradient, int pXTagCount) {
        m_chartSubKey = String.valueOf(getChartSubKeyIndex());

        m_paint = new Paint();
        m_point = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
        m_pointRow = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
        m_pointStart = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);

//		m_nSysUpColor = ResourceManager.getColor(FDTApplication.getApp(), "sys_up");
//		m_nSysDownColor = ResourceManager.getColor(FDTApplication.getApp(), "sys_down");
//		m_nSysBgColor = ResourceManager.getColor(FDTApplication.getApp(), "sys_bg");
//		m_nSysEvenColor = ResourceManager.getColor(FDTApplication.getApp(), "sys_even");
        m_nSysUpColor = AppDefine.ColorDef.UP.getColor();
        m_nSysDownColor = AppDefine.ColorDef.DOWN.getColor();
        m_nSysBgColor = AppDefine.ColorDef.SYS_BG.getColor();
        m_nSysEvenColor = AppDefine.ColorDef.EVEN.getColor();

        m_arrLayerList = new ArrayList<Layer>();
        m_enChartMode = pMode;

        m_nXTagCount = pXTagCount;

        m_bitmapArrowLeft = null;
        m_bitmapArrowRight = null;

        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();

        mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleLinstener(this));
//		gestureDetector = new GestureDetector(getContext(),, new ChartGestureListener());
        mScaleFactor = DEFAULT_SCALEFACTOR;
        final ViewConfiguration configuration = ViewConfiguration.get(getContext());//获得滑动的速率
        mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity();
        mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity();
        mScroller = ScrollerCompat.create(getContext());


        setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                return true;
            }
        });

        //设置view被attach和unattach的事件
        addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
            @Override
            public void onViewDetachedFromWindow(View v) {
                unregisterChart();
                if (m_chartData != null) {
//					FDTLogUtils.d("tingchart","onViewDetachedFromWindow");
                    m_chartData.setEventListener(m_chartSubKey, null);
                }
            }

            @Override
            public void onViewAttachedToWindow(View v) {
                if (m_chartData != null) {
//					FDTLogUtils.d("tingchart","onViewAttachedToWindow");
                    m_chartData.setEventListener(m_chartSubKey, m_listener);
                }
            }
        });
    }

    private void unregisterChart() {
        queryDataHandler.removeCallbacksAndMessages(null);
        DataManager.getDataManager().getQuoteCenter().unregisterChart(
                m_chartSubKey, m_strSymbolCode, m_enChartType);
    }

    @Override
    public void setOnClickListener(OnClickListener l) {
        m_listenerClick = l;
    }

    //在chart被附加时调用,给每一个layer设置数据
    protected ChartData.IChartEventListener m_listener = new ChartData.IChartEventListener() {
        @Override
        public void onRefresh(final ChartData chart, final AppDefine.UpdateMode mode) {
            // final ChartData tChart = new ChartData(chart);

            BaseApp.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (chart.getSymbol() != null) {
                        if (chart.getSymbol().getCode().equals(m_strSymbolCode)) {
                            if (chart.getChartPeroid() == m_enChartType) {
                                if (m_callbackData != null) {
                                    m_callbackData.onReceiveData();
                                }
                                int tSize = m_arrLayerList.size();
//								FDTLogUtils.d("tingchart", "onRefresh");
                                for (int ii = 0; ii < tSize; ii++) {
                                    m_arrLayerList.get(ii).setData(new ChartData(chart), mode);
                                }

                                if (mode == AppDefine.UpdateMode.REFRESH) {
//									FDTLogUtils.d("tingchart1","onRefresh postInvalidateOnAnimation");
                                    ViewCompat.postInvalidateOnAnimation(CoinChart.this);
//									invalidate();
                                }
                            }
                        }
                    }
                }
            });
        }

        /**
         * 用于滑动没有获取新数据时候的重绘，不需要对数据进行重新装载
         * @param chart
         */
        @Override
        public void reDrawChart(final ChartData chart, final int pdataIndex, final float pdataIndexOffset) {
            BaseApp.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (chart.getSymbol() != null) {
                        if (chart.getSymbol().getCode().equals(m_strSymbolCode)) {
                            if (chart.getChartPeroid() == m_enChartType) {
                                int tSize = m_arrLayerList.size();
                                for (int ii = 0; ii < tSize; ii++) {
                                    m_arrLayerList.get(ii).coordinateUpdate(pdataIndex, pdataIndexOffset);
                                }

//								FDTLogUtils.d("tingchart","reDrawChart postInvalidateOnAnimation");
                                ViewCompat.postInvalidateOnAnimation(CoinChart.this);
                            }
                        }
                    }
                }
            });
        }

        @Override
        public int getDisplayDataCount() {
            return CoinChart.this.getDisplayDataCount();
        }

        @Override
        public void showLoadingBar(boolean pIsShow) {
            mIsShowProgressBar = pIsShow;
            if (m_callback != null) {
                m_callback.showLoadingBar(pIsShow, mChartContentLeft);
            }
        }
    };

    public void setSysUpColor(int pColor) {
        m_nSysUpColor = pColor;
    }

    public void setSysDownColor(int pColor) {
        m_nSysDownColor = pColor;
    }

    public void setSysEvenColor(int pColor) {
        m_nSysEvenColor = pColor;
    }

    public void setSymbolCode(String pSymbolCode) {
        unregisterChart();
        m_strSymbolCode = pSymbolCode;
    }

    public String getSymbolCode() {
        return m_strSymbolCode;
    }

    public void setChartMode(ChartModeEnum pMode) {
        m_enChartMode = pMode;
    }

    public ChartModeEnum getChartMode() {
        return m_enChartMode;
    }

    public void setChartType(ChartData.ChartPeroid pType) {
        unregisterChart();
        m_enChartType = pType;
    }

    public ChartData.ChartPeroid getChartType() {
        return m_enChartType;
    }

    public ChartData getChartData() {
        return m_chartData;
    }


    //去查询数据
    private void queryDataAction() {

        if (m_chartData != null) {
            m_chartData.setEventListener(m_chartSubKey, null);
        }

        if (m_callbackData != null) {
            m_callbackData.onQueryData();
        }

        m_chartData = DataManager.getDataManager().getQuoteCenter().queryChart(
                m_chartSubKey, m_strSymbolCode, m_enChartType);
        m_chartData.setEventListener(m_chartSubKey, m_listener);

    }

    /**
     * 图表订阅数据
     */
    public void queryNewData() {
        if (m_strSymbolCode != null && m_strSymbolCode.length() > 0) {

            /**
             * 延迟20ms订阅，如果20ms内有新的请求，cancel之前的请求
             */
            long currentTimeStamp = System.currentTimeMillis();

            if (currentTimeStamp - lastQueryTimeStamp < QUERY_DELAY) {
                queryDataHandler.removeCallbacksAndMessages(null);

            }

            lastQueryTimeStamp = currentTimeStamp;

            queryDataHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    queryNewDataAction();
                }
            }, QUERY_DELAY);

        }
    }

    private void queryNewDataAction() {
        m_chartData = DataManager.getDataManager().getQuoteCenter().queryChart(
                PERIODQUERY, m_strSymbolCode, m_enChartType);
    }


    private long lastQueryTimeStamp = 0;

    private static final int QUERY_DELAY = 20;

    private Handler queryDataHandler = new Handler(Looper.getMainLooper());

    /**
     * 图表订阅数据
     */
    public void queryData() {
        if (m_strSymbolCode != null && m_strSymbolCode.length() > 0) {

            /**
             * 延迟20ms订阅，如果20ms内有新的请求，cancel之前的请求
             */
            long currentTimeStamp = System.currentTimeMillis();

            if (currentTimeStamp - lastQueryTimeStamp < QUERY_DELAY) {
                queryDataHandler.removeCallbacksAndMessages(null);

            }

            lastQueryTimeStamp = currentTimeStamp;

            queryDataHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    queryDataAction();
                }
            }, QUERY_DELAY);

        }
    }

    public void setData(final ChartData outerChartData) {
        BaseApp.runOnUiThread(new Runnable() {
            @Override
            public void run() {

                for (int ii = 0; ii < m_arrLayerList.size(); ii++) {
                    m_arrLayerList.get(ii).setData(outerChartData, AppDefine.UpdateMode.REFRESH);
                }

                ViewCompat.postInvalidateOnAnimation(CoinChart.this);

            }
        });
    }

    public void clearLayers() {
        m_arrLayerList.clear();
    }

    //添加每个图层
    public void addLayer(Layer pLayer) {
        for (Layer tLayer : m_arrLayerList) {
            if (tLayer.getID().equals(pLayer.getID())) {
                throw new RuntimeException("ID is already exist!");
            }
        }

        pLayer.setCallback(new Layer.LayerCallback() {

            @Override
            public void lastPoint(String pLayerID, float x, float y) {

            }

            @Override
            public void pointFeedback(HashMap<String, String> pData, Point pPoint, boolean isPointInLayer) {

            }

            @Override
            public void NeedRedraw() {
                reload(false);
            }

            @Override
            public int getSysUpColor() {
                return m_nSysUpColor;
            }

            @Override
            public int getSysDownColor() {
                return m_nSysDownColor;
            }

            @Override
            public int getSysEvenColor() {
                return m_nSysEvenColor;
            }

            @Override
            public ChartData.ChartPeroid getChartType() {
                return m_enChartType;
            }

            @Override
            public int getXTagCount() {
                return m_nXTagCount;
            }

            @Override
            public int getSysBgColor() {
                return Color.parseColor("#FF4A86EA");
            }

            @Override
            public void pointFeedback(Point pPoint, HashMap<String, String> pData) {
                if (m_callback != null) {
                    m_callback.pointFeedback(pPoint, pData);
                }
            }

            @Override
            public Rect getPanelRect() {
                return new Rect(getLeft(), getTop(), getRight(), getBottom());
            }

            @Override
            public boolean isSimpleMode() {
                return m_bIsSimpleMode;
            }

            @Override
            public Bitmap getArrowLeft() {
                return m_bitmapArrowLeft;
            }

            @Override
            public Bitmap getArrowRight() {
                return m_bitmapArrowRight;
            }

            @Override
            public boolean isCoordinateTextOuterY() {
                return m_bIsCoordinateTextOuterY;
            }

            @Override
            public int getDisplayCount() {
                return CoinChart.this.getDisplayDataCount();
            }

            @Override
            public float getScaleFactor() {
                return mScaleFactor;
            }

            @Override
            public boolean isInMoveMode() {
                return canMove();
            }
        });
        m_arrLayerList.add(pLayer);
        //重画
        reload(false);
    }

    public int getLayerSize() {
        return m_arrLayerList.size();
    }

    public Layer getLayer(int pIndex) {
        if (pIndex < m_arrLayerList.size()) {
            return m_arrLayerList.get(pIndex);
        } else {
            return null;
        }
    }

    public Layer getLayer(String pID) {
        for (Layer tLayer : m_arrLayerList) {
            if (tLayer.getID().equals(pID)) {
                return tLayer;
            }
        }
        return null;
    }

    public void setBorderColor(int pColor) {
        m_nBorderColor = pColor;
    }

    public void setBorderWidth(float pWidth) {
        m_fBorderWidth = pWidth;
    }

    public void setXTagCount(int pCount) {
        m_nXTagCount = pCount;
    }

    public void setSimpleMode(boolean pBool) {
        m_bIsSimpleMode = pBool;
    }

    public boolean removeLayer(int pIndex) {
        if (pIndex >= 0 && pIndex < m_arrLayerList.size()) {
            m_arrLayerList.remove(pIndex);
            reload(false);
            return true;
        }
        return false;
    }

    public boolean removeLayer(String layerID) {
        Layer tTempLayer = null;
        for (Layer tLayer : m_arrLayerList) {
            if (tLayer.getID().equals(layerID)) {
                tTempLayer = tLayer;
                break;
            }
        }

        if (tTempLayer == null) {
            return false;
        } else {
            m_arrLayerList.remove(tTempLayer);
            reload(false);
            return true;
        }
    }

    public boolean removeLayer(Layer pLayer) {
        Layer tTempLayer = null;
        for (Layer tLayer : m_arrLayerList) {
            if (pLayer == tLayer) {
                tTempLayer = tLayer;
                break;
            }
        }

        if (tTempLayer == null) {
            return false;
        } else {
            m_arrLayerList.remove(tTempLayer);
            reload(false);
            return true;
        }
    }

    public void setCallback(FDTChartCallback pCallback) {
        m_callback = pCallback;
    }

    public void setDataCallback(IDataCallback pCallback) {
        m_callbackData = pCallback;
    }

    //重画或者获取数据
    public void reload(boolean pNeedResetData) {
//		FDTLogUtils.d("tingchart", "reload pNeedResetData" + pNeedResetData);
        if (pNeedResetData) {
            int tSize = m_arrLayerList.size();
            for (int ii = 0; ii < tSize; ii++) {
                if (m_chartData != null) {
                    m_arrLayerList.get(ii).setData(new ChartData(m_chartData), AppDefine.UpdateMode.REFRESH);
                }
            }
        } else {
            ViewCompat.postInvalidateOnAnimation(CoinChart.this);
        }
    }

    public void register() {
        // FDTApplication.getApp().getDataManager().getQuoteCenter().getEventBus().register(this);
    }

    public void unregister() {
        // FDTApplication.getApp().getDataManager().getQuoteCenter().getEventBus().unregister(this);
    }

    //把图数据取消订阅,并把数据设为空
    public void cancel() {
        if (mScroller != null) {
            mScroller.abortAnimation();
        }
        m_bLongPress = false;
        //取消订阅的时候把数据清到只剩n条
        if (m_chartData != null) {
            m_chartData.m_networkRequest = 0;
            if (m_listener != null) {
                m_listener.showLoadingBar(false);
            }
            mScaleFactor = DEFAULT_SCALEFACTOR;
        }

        if (m_chartData != null && m_chartData.getCandleData() != null && m_chartData.getCandleData().size() > 0 && m_chartData.getChartPeroid() != ChartData.ChartPeroid.CP_DC) {
            ArrayList<CandleData> candles = m_chartData.getCandleData();
            CandleData candle;
            int deleteNum = candles.size() - m_enChartType.getQueryCount() > 0 ? candles.size() - m_enChartType.getQueryCount() : 0;

            candles.subList(0, deleteNum).clear();
            if (deleteNum > 0)//如果清除的数据大于0，把获取更多开启
            {
                m_chartData.m_nomoredata = false;
            }


//			if(deleteNum != 0)
//			{
//				for (int i = 0; i < deleteNum; i++)
//				{
//					candle = candles.get(0);
//					candles.remove(candle);
//				}
//			}
            //重置数据定位和缩放比例
//			m_chartData.m_dataIndex = deleteNum > 0 ? m_enChartType.getQueryCount()  - (isLandScape()? m_enChartType.getQueryCount()/2 : 60) : 0;
//			m_chartData.m_dataIndexOffset = m_chartData.m_dataIndex;
        }

        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }


        unregisterChart();

        int tSize = m_arrLayerList.size();
        for (int ii = 0; ii < tSize; ii++) {
            m_arrLayerList.get(ii).setData(null, AppDefine.UpdateMode.REFRESH);
        }
    }

    //清除滑动事件点的位置
    public void clearCross() {
        m_pointStart.x = Integer.MIN_VALUE;
        m_pointStart.y = Integer.MIN_VALUE;
        m_point.x = Integer.MIN_VALUE;
        m_point.y = Integer.MIN_VALUE;
        m_pointRow.x = Integer.MIN_VALUE;
        m_pointRow.y = Integer.MIN_VALUE;

        reload(false);
    }

    public void setCoordinateTextOuterY(boolean outer) {
        m_bIsCoordinateTextOuterY = outer;
    }

    //根据传入的spec设置长宽
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int tWidth = measureSize(widthMeasureSpec);
        int tHeight = measureSize(heightMeasureSpec);
//		FDTLogUtils.d("tingchart","onMeasure"+tWidth+" "+tHeight);
        if (m_nMeasureHeight != tHeight || m_nMeasureWidth != tWidth) {
            m_nMeasureHeight = tHeight;
            m_nMeasureWidth = tWidth;
//			FDTLogUtils.d("tingchart","setMeasuredDimension"+tWidth+" "+tHeight);
            setMeasuredDimension(tWidth, tHeight);
        } else {
//			FDTLogUtils.d("tingchart","2setMeasuredDimension"+tWidth+" "+tHeight);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    //获取宽度
    private int measureSize(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = 300;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }

        return result;
    }

    @Override
    public void setOnTouchListener(OnTouchListener l) {

    }

    private void setChartRect(RectF chartRect) {
        mChartRect = chartRect;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        m_paint.setColor(getBorderColor());
        m_paint.setStrokeWidth(m_fBorderWidth);
        m_paint.setAntiAlias(true);
        m_paint.setStyle(Paint.Style.STROKE);

//		RectF tOriChartRect = new RectF(getLeft() + (getWidth() / 40.f), getTop() + (getHeight() / 40.f), getLeft() + (getWidth() * 39 / 40.f), getTop() + (getHeight() * 39 / 40.f));
        //初始化rect为padding为40分之一

        RectF tChartRect = new RectF(getLeft() + (getWidth() / 40.f), getTop() + (getHeight() / 40.f),
                                            getLeft() + (getWidth() * 39 / 40.f), getTop() + (getHeight() * 39 / 40.f));

        RectF tSpaceRect = new RectF();
        //初始化坐标的绘制区域为40分之三
        float textSpaceX = getWidth() * 3 / 40.f;
        float textSpaceY = getWidth() * 3 / 40.f;

        if (m_bIsCoordinateTextOuterY) {
            for (Layer tLayer : m_arrLayerList) {
                PointLocation tPL = tLayer.getOriginPointLocation();//默认为BOTTOMRIGHT
                switch (tPL) {
                    case BOTTOMLEFT:
                        tChartRect.left = getLeft() + (getWidth() * 3 / 40.f);
                        tChartRect.bottom = getTop() + (getHeight() * 37 / 40.f);
                        if (tLayer.isShowPercentAxis() != AxisPercentType.NOPERCENT)//如果要在右侧显示百分比，需要把右侧缩进
                        {
                            tChartRect.right = getLeft() + (getWidth() * 37 / 40.f);
                        }
                        textSpaceY = tChartRect.left - getLeft();
                        textSpaceX = getBottom() - tChartRect.bottom;
                        break;
                    case BOTTOMRIGHT:
                        tChartRect.right = getLeft() + (getWidth() * 36 / 40.f);//扣除了padding 和space的宽度  40分之4
                        tChartRect.bottom = getTop() + (getHeight() * 37 / 40.f);
                        textSpaceY = getRight() - tChartRect.right;//计算textspace的宽度
                        textSpaceX = getBottom() - tChartRect.bottom;
                        break;
                    case TOPLEFT:
                        tChartRect.left = getLeft() + (getWidth() * 3 / 40.f);
                        tChartRect.top = getTop() + (getHeight() * 3 / 40.f);
                        textSpaceY = tChartRect.left - getLeft();
                        textSpaceX = tChartRect.top - getTop();
                        break;
                    case TOPRIGHT:
                        tChartRect.right = getLeft() + (getWidth() * 36 / 40.f);
                        tChartRect.top = getTop() + (getHeight() * 3 / 40.f);
                        textSpaceY = getRight() - tChartRect.right;
                        textSpaceX = tChartRect.top - getTop();
                        break;
                }
            }
        } else {
            for (Layer tLayer : m_arrLayerList) {
                PointLocation tPL = tLayer.getOriginPointLocation();
                switch (tPL) {
                    case BOTTOMLEFT:
                        tChartRect.bottom = getTop() + (getHeight() * 37 / 40.f);
                        textSpaceY = getWidth() * 3 / 40.f;
                        textSpaceX = getBottom() - tChartRect.bottom;
                        break;
                    case BOTTOMRIGHT:
                        if (!is8btcStyle) {
                            tChartRect.bottom = getTop() + (getHeight() * 37 / 40.f);
                            textSpaceY = getWidth() * 4 / 40.f;
                            textSpaceX = getBottom() - tChartRect.bottom;
                        } else {
                            textSpaceY = getWidth() * 4 / 40.f;
                            textSpaceX = (getBottom() - tChartRect.bottom) * 1.4f;
                        }
                        break;
                    case TOPLEFT:

                        tChartRect.top = getTop() + (getHeight() * 3 / 40.f);
                        textSpaceY = getWidth() * 3 / 40.f;
                        textSpaceX = tChartRect.top - getTop();

                        break;
                    case TOPRIGHT:
                        tChartRect.top = getTop() + (getHeight() * 3 / 40.f);
                        textSpaceY = getWidth() * 4 / 40.f;
                        textSpaceX = tChartRect.top - getTop();
                        break;
                }
            }
        }

        tSpaceRect.left = tChartRect.left - getLeft();
        tSpaceRect.top = tChartRect.top - getTop();
        tSpaceRect.right = getRight() - tChartRect.right;
        tSpaceRect.bottom = getBottom() - tChartRect.bottom;

        //画方框
        if (m_IsDrawRect) {
            canvas.drawRect(new RectF(tSpaceRect.left, tSpaceRect.top, tSpaceRect.left + tChartRect.width(), tSpaceRect.top + tChartRect.height()), m_paint);
        }

        for (Layer tLayer : m_arrLayerList) {
            //画坐标桌和点
            tLayer.initializeRect(tChartRect, tSpaceRect, textSpaceX, textSpaceY);
            tLayer.drawLayer(canvas, m_paint, m_point);
        }

//		FDTLogUtils.d("tingchart","(float) (getDisplayDataCount() + 1)"+(float) (getDisplayDataCount() + 1)+"tChartRect.width()"+(tChartRect.width()));
        mStepX = (tChartRect.width()) / ((float) (getDisplayDataCount()));//每个数据的x宽度
        mChartContentLeft = tChartRect.left;
        mChartContentWidth = tChartRect.width();

        if (m_bLongPress)//长按后才出现十字
        {
            for (Layer tLayer : m_arrLayerList) {
                tLayer.drawAvgPriceText(canvas, m_paint);
                tLayer.drawCrossText(canvas, m_paint);
            }
        }

        for (Layer tLayer : m_arrLayerList) {
            tLayer.drawFloatPanel(canvas, m_paint);
            tLayer.drawFloatIndicatorText(m_bLongPress, canvas, m_paint);
        }

        if (m_callback != null) {
            m_callback.didDrawFinished();
        }
    }

    public int getDisplayDataCount() {
//		FDTLogUtils.d("tingchart","getDisplayDataCount"+(getGridDataCount() - 1));
        return (getGridDataCount());
    }

    public int getGridDataCount() {
        int bundleCount = isLandScape() ? m_enChartType.getQueryCount() / 2 : 60; //m_enChartType.getQueryCount() / 2;
        return (int) (bundleCount / mScaleFactor);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int tAction = event.getAction();
        int tX = (int) event.getX();
        int tY = (int) event.getY();
        int tXRow = (int) event.getRawX();
        int tYRow = (int) event.getRawY();

        if (canMove())//可以滑动的情况下再去获取速率
        {
            if (mVelocityTracker == null) {
                mVelocityTracker = VelocityTracker.obtain();
            }
            mVelocityTracker.addMovement(event);

            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
//				FDTLogUtils.d("tingchart", "imzoommode set false");
                mZoomMode = false;
                mZoomFocusX = 0;
            }
            if (canScale()) {
                mScaleDetector.onTouchEvent(event);
            }
        }
        if (mZoomMode) {//如果是在缩放中，只执行缩放事件
            return super.onTouchEvent(event);
        }

        if (tAction == MotionEvent.ACTION_DOWN) {
            mStartClickTime = Calendar.getInstance().getTimeInMillis();
            mScroller.abortAnimation();

            m_pointStart.x = tX;
            m_pointStart.y = tY;
            m_point.x = tX;
            m_point.y = tY;
            m_pointRow.x = tXRow;
            m_pointRow.y = tYRow;

            if (canMove())//如果是在滑动模式下需要拦截父控件的事件
            {
                getParent().requestDisallowInterceptTouchEvent(true);
                onMove(event);//执行onmove事件去请求行情和重绘
            }
            if (mShouldIntercept) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            m_bLongPress = false;

            Timer timer = new Timer(true);
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (m_callback != null) {
//						FDTLogUtils.d("tingchart","m_bLongPress = true");
                        m_bLongPress = true;
                        m_handler.sendEmptyMessage(LONGPRESS);
                        if (m_needLongLongPress) {
                            Timer timer = new Timer(true);
                            timer.schedule(new TimerTask() {
                                @Override
                                public void run() {
                                    if (m_callback != null) {
                                        if (m_bLongPress) {
                                            Date nowTime = new Date();
                                            if (nowTime.getTime() - mllRecordTime.getTime() > m_llPressTime2) {
                                                m_bLongLongPress = true;
                                                m_bLongPress = false;
                                                m_handler.sendEmptyMessage(LONGLONGPRESS);
                                            }
                                        }
                                    }
                                }
                            }, m_llPressTime, m_llPressTime);

                            cancelTime();
                            m_timer = timer;
                            mllRecordTime = new Date();
                        }
                    }
                }
            }, m_lPressTime);

            cancelTime();
            m_timer = timer;

            if (m_callback != null) {
                m_callback.onTouchDown();
            }
            reload(false);
        } else if (tAction == MotionEvent.ACTION_MOVE) {

            if (m_bLongPress == false && (Math.abs(tX - m_point.x) > mTouchSlop || Math.abs(tY - m_point.y) > mTouchSlop)) {
                if ((Math.abs(tY - m_point.y) - Math.abs(tX - m_point.x)) > mTouchSlop && getParent() != null)//如果y上的位移大于x上的，就把父的事件开起来
                {
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                m_point.x = tX;
                m_point.y = tY;
                m_pointRow.x = tXRow;
                m_pointRow.y = tYRow;

                m_bIsDrag = true;

                if (canMove()) {
                    onMove(event);
                }

                if (mShouldIntercept) {
                    reload(false);
                }

//				FDTLogUtils.d("tingchart", "onmove cancel time");
                cancelTime();

            } else if (m_bLongPress && (Math.abs(tX - m_point.x) > 3 || Math.abs(tY - m_point.y) > 3)) {
//				FDTLogUtils.d("tingchart", "onmove cancel time longpress");
                mllRecordTime = new Date();

                getParent().requestDisallowInterceptTouchEvent(true);//长按的时候需要拦截事件，不管是不是canmove的
                m_point.x = tX;
                m_point.y = tY;
                m_pointRow.x = tXRow;
                m_pointRow.y = tYRow;
                reload(false);//长按后移动要移动十字
            } else {
                return super.onTouchEvent(event);
            }
        } else {
            if ((tAction == MotionEvent.ACTION_UP || tAction == MotionEvent.ACTION_CANCEL)) {
                if (canMove()) {
                    //惯性滑动
                    final VelocityTracker velocityTracker = mVelocityTracker;
                    final int pointerId = event.getPointerId(0);
                    velocityTracker.computeCurrentVelocity(500, mMaximumFlingVelocity);
                    final float velocityY = velocityTracker.getYVelocity(pointerId);
                    final float velocityX = velocityTracker.getXVelocity(pointerId);


                    if ((Math.abs(velocityY) > mMinimumFlingVelocity)
                                || (Math.abs(velocityX) > mMinimumFlingVelocity) && m_chartData != null && m_chartData.getCandleData().size() > 0) {
//						FDTLogUtils.d("tingchart", "mMinimumFlingVelocity" + mMinimumFlingVelocity + " mMaxFlingVelocity" + mMaximumFlingVelocity);
                        //如果当前的速率在范围内为fling事件
                        Point surfaceSize = computeScrollSurfaceSize();
                        int startX = (int) m_chartData.m_dataIndex * surfaceSize.x / m_chartData.getCandleData().size();
                        int mContentRectWidth = surfaceSize.x * getDisplayDataCount() / m_chartData.getCandleData().size();
                        int maxScrollX = surfaceSize.x - mContentRectWidth;
//						FDTLogUtils.d("tingchart", "fling startX" + startX + " mContentRectWidth" + mContentRectWidth + " maxScrollX" + maxScrollX + " surfaceSize.x" + surfaceSize.x + " m_chartData.m_dataIndex" + m_chartData.m_dataIndex + " m_chartData.getCandleData().size()" + m_chartData.getCandleData().size() + " velocityX" + velocityX);

                        mScroller.abortAnimation();
                        mScroller.fling(startX, 0, (int) -velocityX, 0, 0, maxScrollX, 0, 0);
                    }
                }

                getParent().requestDisallowInterceptTouchEvent(false);


                if (m_callback != null) {
                    m_callback.onTouchUp();
                    if (tAction == MotionEvent.ACTION_UP)//判断点击事件
                    {
                        long clickDuration = Calendar.getInstance().getTimeInMillis() - mStartClickTime;
                        if (clickDuration < MAX_CLICK_DURATION && !m_bIsDrag) {//down到up的时间在200ms内为点击事件,并且没有move超过一定距离

                            int tSize = m_arrLayerList.size();
                            Layer topLayer = null;
                            boolean touchInlayer = false;

                            for (int ii = tSize - 1; ii >= 0; ii--) {
                                topLayer = m_arrLayerList.get(ii);

                                if (topLayer.IsPointInLayer()) {
                                    touchInlayer = true;
                                    break;
                                }
                            }

                            if (touchInlayer) {
                                m_callback.onClickEvent(topLayer);
                            }
                        }
                    }
                }


            }

            m_bIsDrag = false;

            m_bLongLongPress = false;
            cancelTime();
            m_timer = new Timer(true);

            if (m_bLongPress) {
                m_bLongPress = false;
                m_handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        m_pointStart.x = Integer.MIN_VALUE;
                        m_pointStart.y = Integer.MIN_VALUE;
                        m_point.x = Integer.MIN_VALUE;
                        m_point.y = Integer.MIN_VALUE;
                        m_pointRow.x = Integer.MIN_VALUE;
                        m_pointRow.y = Integer.MIN_VALUE;

                        reload(false);
                    }
                }, LongPressDelay);
            } else {
                m_pointStart.x = Integer.MIN_VALUE;
                m_pointStart.y = Integer.MIN_VALUE;
                m_point.x = Integer.MIN_VALUE;
                m_point.y = Integer.MIN_VALUE;
                m_pointRow.x = Integer.MIN_VALUE;
                m_pointRow.y = Integer.MIN_VALUE;
                reload(false);
            }

        }

//		reload(false);

        return super.onTouchEvent(event);
    }

    private Point computeScrollSurfaceSize() {
        int width = (int) mStepX * m_chartData.getCandleData().size();
        int height = getHeight();
//		FDTLogUtils.d("tingchart","computeScrollSurfaceSize width"+width+" height"+height);
        return new Point(
                                width, height);
    }


    @Override
    public void computeScroll() {
        super.computeScroll();
        //根据滑动到的x，进行moveindex的操作
        if (mScroller.computeScrollOffset()) {
            int scrollPostion = mScroller.getCurrX();
//			float speed = mScroller.getCurrVelocity();
            if (scrollPostion == 0 || m_chartData.getCandleData().size() == 0) {
                return;
            }
            Point surfaceSize = computeScrollSurfaceSize();
            int startX = m_chartData.m_dataIndex * surfaceSize.x / m_chartData.getCandleData().size();
            int f = (scrollPostion - startX) * m_chartData.getCandleData().size() / surfaceSize.x;
//			FDTLogUtils.d("tingchart1", "computeScroll speed" + speed + " scrollPostion" + scrollPostion + " startX" + startX + " f" + f + " m_chartData.m_dataIndex" + m_chartData.m_dataIndex + " m_chartData.getCandleData().size()" + m_chartData.getCandleData().size());
            if (f >= DEFAULT_SCALEFACTOR || f <= -1.0f) {
                int i = (int) f;//i为步长
//				FDTLogUtils.d("tingchart1", "computeScroll moveindex" + i);
                m_chartData.moveIndex(m_chartSubKey, i);//调用移动函数
            } else {
                ViewCompat.postInvalidateOnAnimation(CoinChart.this);//computeScroll依赖于重绘
            }

        }

    }

    protected void onMove(MotionEvent motionEvent) {
        float x = motionEvent.getX();
        int action = motionEvent.getAction();
        if (action == MotionEvent.ACTION_DOWN) {
//			FDTLogUtils.d("tingchart","onmove action == 0"+x);
            mTouchStartX = x;
        } else if (action == MotionEvent.ACTION_MOVE) {//如果是滑动
//			FDTLogUtils.d("tingchart","onmove action == 2");
//			FDTLogUtils.d("tingchart","mStepX"+ mStepX +"mTouchStartX - x"+(mTouchStartX - x)+"mTouchStartX"+ mTouchStartX +"x"+x);
            float f = (mTouchStartX - x) / mStepX;
//			FDTLogUtils.d("tingchart","mStepX"+f);
            if (f >= DEFAULT_SCALEFACTOR || f <= -1.0f) {
                int i = (int) f;//i为步长
                mTouchStartX = x + ((f - ((float) i)) * mStepX);//修改touchstart的值
//				FDTLogUtils.d("tingchart","mTouchStartX moveIndex"+ mTouchStartX);
                m_chartData.moveIndex(m_chartSubKey, i);//调用移动函数
            }
        }
    }

    protected void onZoom(float pscaleFactor, float pfocusX) {
        int displayDataCount = getDisplayDataCount();
        mScaleFactor *= pscaleFactor;
        if (mScaleFactor > 2.7f) {//K线放大，最大放大至30根
            mScaleFactor = 2.7f;
        } else if (mScaleFactor < 0.25f) {//当K线缩小到320根时，显示折线，并且不可再缩小，只能左右拖动
            mScaleFactor = 0.25f;
        }
//		FDTLogUtils.d("tingchart","mScaleFactor:"+mScaleFactor);
        //根据当前放大区域在屏幕中的位置，计算前面的项和后面的项的比例，计算需要改变的index的大小

//		if(mZoomFocusX == 0)//只在按下的时候赋值
//		{
//			mZoomFocusX = (int)pfocusX;
//		}
        float zoomRate = (pfocusX - mChartContentLeft) / mChartContentWidth;
//		FDTLogUtils.d("tingchart","zoomRate"+zoomRate);


        m_chartData.zoom(m_chartSubKey, displayDataCount, getDisplayDataCount(), zoomRate);
    }

    private void cancelTime() {
        if (m_timer != null) {
            m_timer.cancel();
            m_timer = null;
        }
    }

    public interface FDTChartCallback {
        public void didDrawFinished();

        public void onTouchDown();

        public void onTouchUp();

        public void onLongPress(Point pRowPoint, Point pPoint, String pPrice, Layer.ChartTypeEnum pType);

        public void onLongLongPress(Point pRowPoint, Point pPoint, String pPrice, Layer.ChartTypeEnum pType);

        public void pointFeedback(Point pPoint, HashMap<String, String> pData);

        public void onClickEvent(Layer layer);

        void showLoadingBar(boolean pIsShow, float pChartLeft);
    }

    public interface IDataCallback {
        public void onQueryData();

        public void onReceiveData();
    }

    private Handler m_handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int tWhat = msg.what;
            if (tWhat == LONGPRESS) {
                int tSize = m_arrLayerList.size();
                for (int ii = 0; ii < tSize; ii++) {
                    Layer layer = m_arrLayerList.get(ii);

                    if (layer.needCrossLing() && layer.IsPointInLayer()) {
                        m_callback.onLongPress(m_pointRow, m_point, layer.getYText(), layer.getType());
                    }
                }
                reload(false);
            } else if (tWhat == LONGLONGPRESS) {
                int tSize = m_arrLayerList.size();
                for (int ii = 0; ii < tSize; ii++) {
                    Layer layer = m_arrLayerList.get(ii);

                    if (layer.needCrossLing() && layer.IsPointInLayer()) {
                        m_callback.onLongLongPress(m_pointRow, m_point, layer.getYText(), layer.getType());
                    }
                }
                reload(false);
            }
        }
    };

    @Override
    protected void onDetachedFromWindow() {
        if (m_timer != null) {
            m_timer.cancel();
            m_timer = null;
        }
        super.onDetachedFromWindow();
    }
}
